﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;
using YJKArch.Utils.Generics;

namespace YJKArch.Utils
{
	public class Common
	{
		public static List<DimensionType> GetDimensionTypes(Autodesk.Revit.DB.Document doc)
		{
			List<DimensionType> list = new List<DimensionType>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(DimensionType)).ToElements())
			{
				DimensionType item = element as DimensionType;
				list.Add(item);
			}
			return list;
		}

		public static List<WallType> GetWallTypes(Autodesk.Revit.DB.Document doc)
		{
			List<WallType> list = new List<WallType>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(WallType)).ToElements())
			{
				WallType item = element as WallType;
				list.Add(item);
			}
			return list;
		}

		public static List<TextNoteType> GetTextNoteTypes(Autodesk.Revit.DB.Document doc)
		{
			List<TextNoteType> list = new List<TextNoteType>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(TextNoteType)))
			{
				TextNoteType item = element as TextNoteType;
				list.Add(item);
			}
			return list;
		}

		public static List<GridType> GetGridTypes(Autodesk.Revit.DB.Document doc)
		{
			List<GridType> list = new List<GridType>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(GridType));
			foreach (Element element in filteredElementCollector)
			{
				GridType item = (GridType)element;
				list.Add(item);
			}
			return list;
		}

		public static double MMtoIntch(double val)
		{
			return val / 304.8;
		}

		public static double IntchtoMM(double val)
		{
			return val * 304.8;
		}

		public static int Chr2AscII(string character)
		{
			if (character.Length == 1)
			{
				return (int)new ASCIIEncoding().GetBytes(character)[0];
			}
			throw new Exception("Character is not valid.");
		}

		public static string AscII2Chr(int asciiCode)
		{
			if (asciiCode >= 0 && asciiCode <= 255)
			{
				ASCIIEncoding asciiencoding = new ASCIIEncoding();
				byte[] bytes = new byte[]
				{
					(byte)asciiCode
				};
				return asciiencoding.GetString(bytes);
			}
			throw new Exception("ASCII Code is not valid.");
		}

		public static bool IsCharacterWithAxisNummber(string name, ref int ascII)
		{
			if (name.Length == 1)
			{
				string character = new string(name[0], 1);
				ascII = Common.Chr2AscII(character);
				if ((ascII >= 65 && ascII <= 90) || (ascII >= 97 && ascII <= 122))
				{
					return true;
				}
			}
			return false;
		}

		public static bool IsNummbersWithAxisNummber(string name, ref int nummber)
		{
			for (int i = 0; i < name.Length; i++)
			{
				int num = Common.Chr2AscII(new string(name[i], 1));
				if (num < 48 || num > 57)
				{
					return false;
				}
			}
			nummber = (int)Convert.ToInt16(name);
			return true;
		}

		public static string CharacterAxiseNummberIncrease(string chrNumb)
		{
			int num = -1;
			if (!Common.IsCharacterWithAxisNummber(chrNumb, ref num))
			{
				return chrNumb;
			}
			if (num == 90 || num == 122)
			{
				return chrNumb;
			}
			if (num == 72 || num == 78 || num == 104 || num == 110)
			{
				return Common.AscII2Chr(num + 2);
			}
			return Common.AscII2Chr(num + 1);
		}

		public static string CharacterAxiseNummberDecreasing(string chrNumb)
		{
			int num = -1;
			if (!Common.IsCharacterWithAxisNummber(chrNumb, ref num))
			{
				return chrNumb;
			}
			if (num == 65 || num == 97)
			{
				return chrNumb;
			}
			if (num == 74 || num == 80 || num == 106 || num == 112)
			{
				return Common.AscII2Chr(num - 2);
			}
			return Common.AscII2Chr(num - 1);
		}

		public static void AllCharacterAxises(Autodesk.Revit.DB.Document doc, ref List<Common.GridAndInfos> nummbers)
		{
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Grid)).ToElements())
			{
				Grid grid = element as Grid;
				string name = grid.Name;
				int num = -1;
				if (Common.IsCharacterWithAxisNummber(name, ref num))
				{
					Common.GridAndInfos item = new Common.GridAndInfos(Common.Chr2AscII(new string(name[0], 1)), grid);
					nummbers.Add(item);
				}
			}
		}

		public static void AllNummbersAxises(Autodesk.Revit.DB.Document doc, ref List<Common.GridAndInfos> nummbers)
		{
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Grid)).ToElements())
			{
				Grid grid = element as Grid;
				string name = grid.Name;
				int num = -1;
				if (Common.IsNummbersWithAxisNummber(name, ref num))
				{
					Common.GridAndInfos item = new Common.GridAndInfos((int)Convert.ToInt16(name), grid);
					nummbers.Add(item);
				}
			}
		}

		public static bool isDuplicationName(Autodesk.Revit.DB.Document doc, string testName, ref Grid duplicationNameGrid)
		{
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Grid)).ToElements())
			{
				Grid grid = element as Grid;
				if (grid.Name.CompareTo(testName) == 0)
				{
					duplicationNameGrid = grid;
					return true;
				}
			}
			return false;
		}

		public static void ChangeGridName(Autodesk.Revit.DB.Document doc, Grid grid, string newName)
		{
			Grid grid2 = null;
			if (Common.isDuplicationName(doc, newName, ref grid2))
			{
				string name = grid.Name;
				grid.Name = "temp";
				grid2.Name = name;
			}
			grid.Name = newName;
		}

		public static void get3dViewName(Autodesk.Revit.DB.Document doc, View3D view3d)
		{
			List<int> list = new List<int>();
			FilteredElementIterator elementIterator = new FilteredElementCollector(doc).OfClass(typeof(Autodesk.Revit.DB.View)).GetElementIterator();
			elementIterator.Reset();
			while (elementIterator.MoveNext())
			{
				Element element = elementIterator.Current;
				Autodesk.Revit.DB.View view = element as Autodesk.Revit.DB.View;
				if (view != null && !view.IsTemplate && (int)view.ViewType == 4)
				{
					string name = view.Name;
					string text = "局部三维视图";
					int num = name.LastIndexOf(text);
					if (num > -1)
					{
						int item = Convert.ToInt32(name.Substring(num + text.Length));
						list.Add(item);
					}
				}
			}
			list.Sort();
			int num2 = 0;
			if (list.Count > 0)
			{
				num2 = list[list.Count - 1];
			}
			view3d.Name = "局部三维视图" + (num2 + 1).ToString();
		}

		public static void UpdateModel(UIDocument uiDoc, bool autoJoin)
		{
			uiDoc.Document.Regenerate();
			if (autoJoin)
			{
				uiDoc.Document.AutoJoinElements();
			}
			uiDoc.RefreshActiveView();
		}

		public static List<Material> GetAllMaterial(Autodesk.Revit.DB.Document doc)
		{
			IEnumerable<Element> enumerable = new FilteredElementCollector(doc).OfClass(typeof(Material)).ToElements();
			List<Material> list = new List<Material>();
			foreach (Element element in enumerable)
			{
				list.Add(element as Material);
			}
			return list;
		}

		public static List<Level> GetSortLevels(Autodesk.Revit.DB.Document doc, double bottom, double top)
		{
			List<Level> list = new List<Level>();
			foreach (Element element in new FilteredElementCollector(doc).OfClass(typeof(Level)).ToElements())
			{
				Level level = element as Level;
				double elevation = level.Elevation;
				if (Geometry.Greaterthan_Or_Equal(elevation, bottom) && Geometry.Lessthan_Or_Equal(elevation, top))
				{
					list.Add(level);
				}
			}
			list.Sort(new LevelComparer());
			return list;
		}

		protected static List<Grid> GetAllGridInCurrentView(UIApplication uiApp)
		{
			List<Grid> list = new List<Grid>();
			ElementId id = uiApp.ActiveUIDocument.ActiveView.Id;
			foreach (Element element in new FilteredElementCollector(uiApp.ActiveUIDocument.Document, id).OfClass(typeof(Grid)).ToElements())
			{
				Grid item = element as Grid;
				list.Add(item);
			}
			return list;
		}

		protected static List<XYZ> IntersectGridAndGrids(Grid selGrid, List<Grid> grids)
		{
			Curve curve = selGrid.Curve;
			List<XYZ> list = new List<XYZ>();
			foreach (Grid grid in grids)
			{
				Grid grid2 = grid as Grid;
				IntersectionResultArray intersectionResultArray;
                if (!(grid2.Id == selGrid.Id) && (int)grid2.Curve.Intersect(curve, out intersectionResultArray) == 8)
				{
					foreach (object obj in intersectionResultArray)
					{
						IntersectionResult intersectionResult = (IntersectionResult)obj;
						if (intersectionResult.XYZPoint != null)
						{
							list.Add(intersectionResult.XYZPoint);
						}
					}
				}
			}
			return Common.UniqueAndSortIntersectPoints(curve, list);
		}

		public static Curve GetPickSegementWithGrid(UIApplication uiApp, Grid selGrid, XYZ pickPos)
		{
			Curve curve = selGrid.Curve;
			List<Grid> allGridInCurrentView = Common.GetAllGridInCurrentView(uiApp);
			List<XYZ> list = Common.IntersectGridAndGrids(selGrid, allGridInCurrentView);
			if (list.Count < 2)
			{
				return curve;
			}
			double num = double.MaxValue;
			int i = 0;
			int num2 = -1;
			while (i < list.Count - 1)
			{
				XYZ xyz = list[i];
				XYZ xyz2 = list[i + 1];
				double num3 = xyz.DistanceTo(pickPos);
				num3 += xyz2.DistanceTo(pickPos);
				if (num3 < num)
				{
					num = num3;
					num2 = i;
				}
				i++;
			}
			if (num2 == -1)
			{
				return null;
			}
			Curve result = null;
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ xyz3 = list[num2];
				XYZ xyz4 = list[num2 + 1];
				XYZ center = arc.Center;
				double startAngle = XYZ.BasisX.AngleOnPlaneTo(xyz3 - center, XYZ.BasisZ);
				double endAngle = XYZ.BasisX.AngleOnPlaneTo(xyz4 - center, XYZ.BasisZ);
				result = uiApp.ActiveUIDocument.Document.CreatYJKArc(arc.Center, arc.Radius, startAngle, endAngle, XYZ.BasisX, XYZ.BasisY);
			}
			Line line = curve as Line;
			if (null != line)
			{
				result = YJKLineEx.YJKGetBound(list[num2], list[num2 + 1]);
			}
			return result;
		}

		public static List<Curve> GetSegementsWithGrid(UIApplication uiApp, Grid selGrid, List<Grid> allGrids)
		{
			List<Curve> list = new List<Curve>();
			Curve curve = selGrid.Curve;
			if (allGrids == null)
			{
				allGrids = Common.GetAllGridInCurrentView(uiApp);
			}
			List<XYZ> list2 = Common.IntersectGridAndGrids(selGrid, allGrids);
			if (list2.Count < 2)
			{
				list.Add(curve);
				return list;
			}
			for (int i = 0; i < list2.Count - 1; i++)
			{
				Arc arc = curve as Arc;
				if (null != arc)
				{
					XYZ xyz = list2[i];
					XYZ xyz2 = list2[i + 1];
					XYZ center = arc.Center;
					double num = XYZ.BasisX.AngleOnPlaneTo(xyz - center, XYZ.BasisZ);
					double num2 = XYZ.BasisX.AngleOnPlaneTo(xyz2 - center, XYZ.BasisZ);
					if (num2 < num)
					{
						num -= Math.PI*2;
					}
					Arc item = uiApp.ActiveUIDocument.Document.CreatYJKArc(arc.Center, arc.Radius, num, num2, XYZ.BasisX, XYZ.BasisY);
					list.Add(item);
				}
				Line line = curve as Line;
				if (null != line)
				{
					Line item2 = YJKLineEx.YJKGetBound(list2[i], list2[i + 1]);
					list.Add(item2);
				}
			}
			return list;
		}

		public static List<XYZ> UniqueAndSortIntersectPoints(Curve curve, List<XYZ> intersectPoints)
		{
			Arc arc = curve as Arc;
			if (null != arc)
			{
				XYZ hyendPoint = arc.GetEndPoint(0);
				if (arc.Normal.Z < 0.0)
				{
					hyendPoint = arc.GetEndPoint(1);
				}
				intersectPoints.Sort(new AngleComparer(hyendPoint, arc.Center));
			}
			Line line = curve as Line;
			if (null != line)
			{
				XYZ hyendPoint2 = line.GetEndPoint(0);
				intersectPoints.Sort(new DistanceComparer(hyendPoint2));
			}
			IEnumerable<XYZ> enumerable = intersectPoints.Distinct(new Comparint<XYZ>((XYZ x, XYZ y) => x != null && y != null && x.DistanceTo(y) < 0.001));
			List<XYZ> list = new List<XYZ>();
			foreach (XYZ item in enumerable)
			{
				list.Add(item);
			}
			return list;
		}

		public static int GetInt(double a)
		{
			if (a == 0.0)
			{
				return 0;
			}
			double num;
			if (a > 0.0)
			{
				num = a + 0.99999999999999989;
			}
			else
			{
				num = a + -0.999999999999999;
			}
			return (int)num;
		}

		public static int GetTextByteLength(string str)
		{
			return Encoding.Default.GetBytes(str).Length;
		}

		public static bool IsValidating(string numStr, double minRange, double maxRange)
		{
			try
			{
				if (numStr.Trim().CompareTo("") == 0)
				{
					return false;
				}
				if (numStr.Length > 1 && numStr.Substring(0, 1).CompareTo("0") == 0)
				{
					return false;
				}
				double val = Convert.ToDouble(numStr);
				if (Geometry.LessThan(val, minRange))
				{
					return false;
				}
				if (Geometry.GreaterThan(val, maxRange))
				{
					return false;
				}
			}
			catch (Exception)
			{
				return false;
			}
			return true;
		}

		public static int Rounding(double value)
		{
			return (int)(value * 10.0 + 0.5) / 10;
		}

		private const double _eps = 1E-09;

		public class GridAndInfos
		{
			public GridAndInfos(int nummber, Grid grid)
			{
				this.m_Nummber = nummber;
				this.m_Grid = grid;
			}

			public static bool operator <(Common.GridAndInfos g1, Common.GridAndInfos g2)
			{
				return g1.m_Nummber < g2.m_Nummber;
			}

			public static bool operator >(Common.GridAndInfos g1, Common.GridAndInfos g2)
			{
				return g1.m_Nummber > g2.m_Nummber;
			}

			public static bool operator !=(Common.GridAndInfos g1, Common.GridAndInfos g2)
			{
				return g1.m_Nummber != g2.m_Nummber;
			}

			public static bool operator ==(Common.GridAndInfos g1, Common.GridAndInfos g2)
			{
				return g1.m_Nummber == g2.m_Nummber;
			}

			public override int GetHashCode()
			{
				return (this.m_Nummber ^ this.m_Nummber >> 16) * 352654597;
			}

			public bool Equals(Common.GridAndInfos other)
			{
				return !(other == null) && this.m_Grid == other.m_Grid && this.m_Nummber == other.m_Nummber;
			}

			public override bool Equals(object obj)
			{
				return this.Equals((Common.GridAndInfos)obj);
			}

			public int m_Nummber;

			public Grid m_Grid;
		}
	}
}
